package com.axin.auth.service;

import com.axin.common.core.constant.CacheConstants;
import com.axin.common.core.constant.SecurityConstants;
import com.axin.common.core.domain.model.LoginBody;
import com.axin.common.core.domain.web.AjaxResult;
import com.axin.common.core.exception.ServiceException;
import com.axin.common.core.exception.user.CaptchaException;
import com.axin.common.core.exception.user.CaptchaExpireException;
import com.axin.common.core.utils.ServletUtils;
import com.axin.common.redis.utils.RedisUtils;
import com.axin.common.security.model.LoginUser;
import com.axin.common.security.service.TokenService;
import com.axin.system.api.RemoteConfigService;
import com.axin.system.api.RemoteUserService;
import com.axin.system.api.domain.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 登录校验方法
 *
 * @Author 阿欣
 * @Date 2021/8/18 19:02
 **/
@Component
public class SysLoginService {

    @Autowired
    private RemoteConfigService configService;


    @Autowired
    private RemoteUserService userService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisUtils redisUtils;

    @Resource
    private AuthenticationManager authenticationManager;

    /**
     * 登录验证
     *
     * @param loginBody 用户登录表单填写信息
     * @return
     */
    public String login(LoginBody loginBody) {

        HttpServletRequest request = ServletUtils.getRequest();
        boolean captchaOnOff = configService.selectCaptchaOnOff();
        // 验证码开关
        if (captchaOnOff) {
            validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid(), request);
        }

        // 用户验证
        Authentication authentication = null;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword()));
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                throw new ServiceException("用户不存在/密码错误");
            } else {
                throw new ServiceException(e.getMessage());
            }
        }

        LoginUser loginUser = (LoginUser) authentication.getPrincipal();

        // 记录登录信息
        recordLoginInfo(loginUser.getUserId());

        // 生成token
        return tokenService.createToken(loginUser);
    }


    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code     验证码
     * @param uuid     唯一标识
     * @return 结果
     */
    public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
        String captcha = redisUtils.get(verifyKey);
        redisUtils.delete(verifyKey);
        if (captcha == null) {
//            asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
            throw new ServiceException("验证码过期");
        }
        if (!code.equalsIgnoreCase(captcha)) {
//            asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"), request);
            throw new ServiceException("验证码错误");
        }
    }


    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(ServletUtils.getClientIP());
        sysUser.setLoginDate(new Date());
        userService.updateUserProfile(sysUser);

    }

}
